//
// Created by F1997 on 2024/12/24.
//

#include "PcapUtils.h"


namespace ntp {

    // 行情1先到包的计数器
    std::atomic<int> Line1Count(0);
    // 行情2先到包的计数器
    std::atomic<int> Line2Count(0);

    // 时间差
    std::atomic<long long> tmDff(0.000000000);

    // pcap文件模式
    void PcapUtils::readPcapFile() {
        std::cout << "read pcap file" << std::endl;

        char errbuff[PCAP_ERRBUF_SIZE];
        const char *filename = "/tmp/tmp.FdUHWCPhyb/data/out500_ens3f0__00030_20241017124001.pcap"; // 替换为你的pcap文件名

        // 打开pcap文件
        pcap_t *pcap = pcap_open_offline(filename, errbuff);
        if (pcap == nullptr) {
            //std::cerr << "无法打开文件: " << errbuff << std::endl;
            SPDLOG_LOGGER_INFO(my_logger, "无法打开文件: {}", errbuff);
        }

        // 读取和打印 pcap文件中的每个数据包
        const u_char *packet;
        struct pcap_pkthdr header; // pcap 包头部
        int i= 0;
        while ((packet = pcap_next(pcap, &header)) != nullptr) {
            std::cout << "得到数据包，长度: " << header.len << " caplen/数据包物理长度: " << header.caplen << " 时间: " << header.ts.tv_sec << "." << header.ts.tv_usec << std::endl;
            // 打印更多的数据包信息
/*        for (int i = 0; i < header.caplen; i++) {
            printf("%02x ", packet[i]); // 以十六进制显示原始载荷数据
        }*/

            //compareTraffic.writeTraffic1(header);
            //CompareTraffic::writeTraffic1(header);
            i++;

            //packet = pcap_next(pcap, &header);
        }

        // 关闭 pcap 句柄
        pcap_close(pcap);
        std::cout << "包总数" << i << std::endl;
    }

    // 检查是否到达计数起点
    bool PcapUtils::checkIsStart(std::chrono::system_clock::time_point startTime, int offset) {
        // 当前时间是否 >= 启动时间 + 偏移时间
        // 获取当前时间作为启动时间
        //return (std::chrono::system_clock::now() >= startTime + std::chrono::seconds(offset)) ? true : false;
        return (std::chrono::system_clock::now() >= startTime + std::chrono::seconds(offset)); // 简化后
    }


// 从网络接口读取数据包并解析，pcap_next_ex 方式 = 会报错，对‘pcap_open’未定义的引用
/*int PcapUtils::readNetworkInterface() {
    pcap_if_t *alldevs;
    pcap_t *handle;
    char errbuf[PCAP_ERRBUF_SIZE];
    const unsigned char *packet; // 指向的是包的原始数据载荷
    struct pcap_pkthdr header; // 包头中包含了时间戳、捕获长度和原始数据长度等信息
    int res;

     // 获取网络接口
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) {
        fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
        return 1;
    }

     // 打开网络接口
    handle = pcap_open(alldevs->name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf);
    if (handle == NULL) {
        fprintf(stderr, "Couldn't open device %s: %s\n", alldevs->name, errbuf);
        pcap_freealldevs(alldevs);
        return 2;
    }

    pcap_freealldevs(alldevs);

     // 读取并解析网络包
    // pcap_next_ex()函数会阻塞等待，直到捕获到一个网络包或超时
    //if (pcap_loop(handle, 10, packet_handler, reinterpret_cast<u_char*>(&compareTraffic)) < 0)  // pcap_loop()函数会阻塞等待，直到捕获到一个网络包或超时
    while ((res = pcap_next_ex(handle, reinterpret_cast<pcap_pkthdr **>(&header), &packet)) >= 0) {
        if (res == 0)
             // 超时
            continue;

         // 包头信息
        printf("Timestamp: %lld.%lld\n", header.ts.tv_sec, header.ts.tv_usec);
        printf("Caplen: %d\n", header.caplen);
        printf("Len: %d\n", header.len);

         // 有效载荷
        printf("Packet: ");
        for (int i = 0; i < header.caplen; i++) {
            printf("%02x ", packet[i]);
        }
        printf("\n");
    }

    if (res == -1) {
        fprintf(stderr, "Error reading the packets: %s\n", pcap_geterr(handle));
        return 3;
    }

    pcap_close(handle);
    return 0;

}*/

    // 从网卡获取
    int PcapUtils::readNetworkIfaceLine(std::string sectionId, std::chrono::system_clock::time_point startTime,
                                        IniReader* iniCfg, SafeQueue<MarketData>* data_queue, std::string debug) {

        // 从配置文件中获取配置
        std::string device = iniCfg->ReadString(sectionId.data(), "device","");
        std::string sourceIP = iniCfg->ReadString(sectionId.data(), "sourceIP","");
        std::string sourcePort = iniCfg->ReadString(sectionId.data(), "sourcePort","");
        std::string destinationIP = iniCfg->ReadString(sectionId.data(), "destinationIP","");
        std::string destinationPort = iniCfg->ReadString(sectionId.data(), "destinationPort","");
        std::string filterStr1 = iniCfg->ReadString(sectionId.data(), "filterStr",""); // 抓包过滤条件
        // dst 239.3.41.71 and port 21001 或者 host 239.3.41.71 and port 21001
        std::string filterStr = "dst "+destinationIP+" and port " + destinationPort; // dst host

        std::string target_time_all = iniCfg->ReadString("MODE", "target_time_all","");
        int exchange_id = iniCfg->ReadInt("MODE", "exchange_id",0);

        std::string packetMode = iniCfg->ReadString("MODE", "packetMode","");
        if (packetMode == "0") {
            SPDLOG_LOGGER_INFO(my_logger,"{}, 使用pcap库获取网络数据包", sectionId);
        }

        char errbuf[PCAP_ERRBUF_SIZE];
        pcap_t *handle;

        std::ofstream outFile("pcap_out_" + sectionId + ".csv");

        // 网络接口名称
        const char *dev = device.c_str(); //"ens33";

        // 创建 pcap 句柄
        handle = pcap_create(dev, errbuf);
        if (handle == NULL) {
            //fprintf(stderr, "无法创建 pcap 句柄: %s\n", errbuf);
            SPDLOG_LOGGER_ERROR(my_logger, "无法创建 pcap 句柄: %s\n", errbuf);
            return 1;
        }

        // 设置纳秒级时间戳精度
        // 无(毫秒)，PCAP_TSTAMP_PRECISION_NANO(不一定都是9位) ，PCAP_TSTAMP_PRECISION_MICRO(不一定都是六位)
        // t1=1739242273 t2=235530，t1=1739242599 t2=998971747，t1=1739242518 t2=683691
        if (pcap_set_tstamp_precision(handle, PCAP_TSTAMP_PRECISION_NANO) != 0) {// PCAP_TSTAMP_PRECISION_MICRO, PCAP_TSTAMP_PRECISION_NANO
            //fprintf(stderr, "设置纳秒级时间戳精度失败: %s\n", pcap_geterr(handle));
            SPDLOG_LOGGER_ERROR(my_logger, "设置纳秒级时间戳精度失败: {}", pcap_geterr(handle));
            // 也可以选择在这里退出，如果纳秒级别时间戳是必需的
        }

        // 设置捕获参数
        if (pcap_set_snaplen(handle, 65535) != 0) { // 设置最大捕获长度
            //std::cerr << "Error setting snaplen: " << pcap_geterr(handle) << std::endl;
            SPDLOG_LOGGER_ERROR(my_logger, "设置最大捕获长度失败: {}", pcap_geterr(handle));
            return -1;
        }

        if (pcap_set_promisc(handle, 1) != 0) { // 设置混杂模式
            //std::cerr << "Error setting promiscuous mode: " << pcap_geterr(handle) << std::endl;
            SPDLOG_LOGGER_ERROR(my_logger, "设置混杂模式失败: {}", pcap_geterr(handle));
            // goto cleanup; 跳转到错误处理逻辑
            return -1;
        }

        //if (pcap_set_timeout(handle, 1000) != 0) { // 设置超时时间（毫秒） = 是否有必要，报错？？？
        //    std::cerr << "Error setting timeout: " << pcap_geterr(handle) << std::endl;
        //    //goto cleanup;
        //    return -1;
        //}

        // 设置即使模式，为了使收到的报文尽快给用户的处理程序，需要设置成 immediate 模式
        if (pcap_set_immediate_mode(handle, 0) != 0){ // 0:禁用立即模式，1:立即模式，一个是批量，一个是立即收？？？
            //std::cerr << "Error setting timeout: " << pcap_geterr(handle) << std::endl;
            SPDLOG_LOGGER_ERROR(my_logger, "设置时间戳失败: {}", pcap_geterr(handle));
            return -1;
        }
        // 设置缓冲区大小
        if (pcap_set_buffer_size(handle, 1024 * 1024 * 10) != 0) { // 设置缓冲区大小，单位为字节
            //std::cerr << "Error setting buffer size: " << pcap_geterr(handle) << std::endl;
            SPDLOG_LOGGER_ERROR(my_logger, "设置缓冲区失败: {}", pcap_geterr(handle));
            return -1;
        }

        // 激活 pcap 句柄
        if (pcap_activate(handle) != 0) {
            //fprintf(stderr, "激活 pcap 句柄失败: %s\n", pcap_geterr(handle));
            SPDLOG_LOGGER_ERROR(my_logger, "激活 pcap 句柄失败: {}", pcap_geterr(handle));
            pcap_close(handle);
            return 1;
        }

        // 设置过滤器
        struct bpf_program fp;
        char filter_exp2[] = "host 192.168.192.1"; // 过滤IP数据包，等价的写法，c_str 后为 const char *
        const char *filter_exp = filterStr.c_str() ;
        if (pcap_compile(handle, &fp, filter_exp, 0, PCAP_NETMASK_UNKNOWN) < 0) {
            //fprintf(stderr, "无法解析过滤器 %s: %s\n", filter_exp, pcap_geterr(handle));
            SPDLOG_LOGGER_ERROR(my_logger, "无法解析过滤器 %s: %s\n", filter_exp, pcap_geterr(handle));
            exit(EXIT_FAILURE);
        }
        if (pcap_setfilter(handle, &fp) < 0) {
            //fprintf(stderr, "无法应用过滤器 %s: %s\n", filter_exp, pcap_geterr(handle));
            SPDLOG_LOGGER_ERROR(my_logger, "无法应用过滤器 %s: %s\n", filter_exp, pcap_geterr(handle));
            exit(EXIT_FAILURE);
        }

        // 检查实际的时间戳精度
        int tstamp_precision = pcap_get_tstamp_precision(handle);

        struct pcap_pkthdr *header;
        const u_char *packet;
        int res;

        try {
            auto currentTime = std::chrono::system_clock::now();
            // 当前时间小于指定时间，则忙等
            while ( currentTime.time_since_epoch().count() <= parse_date_to_timestamp(target_time_all)*1000000000 ) {
                // 当前时间小于目标时间，等待100毫秒后再次检查
                //std::this_thread::sleep_for(std::chrono::milliseconds(1));
                std::this_thread::sleep_for(std::chrono::nanoseconds(10)); // 10ns
                currentTime = std::chrono::system_clock::now();
                //std::cout << "1 忙等中。。。" << std::endl;
            }

            //std::cout << "pcap开始抓取数据包 tm:" << currentTime.time_since_epoch().count() << " > " << parse_date_to_timestamp(target_time_all)*1000000000 << std::endl;
            SPDLOG_LOGGER_INFO(my_logger,"{} 开始抓取数据: {}",sectionId.data(), filterStr);
            int pkgCount = 0; // 抓包计数器
            int statistic_num = 0; // 入队计数器
            // 时间容器
            //std::vector<std::chrono::system_clock::time_point> timeContainer;
            std::vector<uint64_t> timeContainer;
            std::vector<struct timeval> timestamps;
            long total_diff_us = 0;
            //auto statisticTime = std::chrono::system_clock::now();
            auto statisticTime = std::chrono::system_clock::now(); // 10
            // 捕获循环
            while ((res = pcap_next_ex(handle, &header, &packet)) >= 0 && Global::g_exit == 0 ) { // header=报文头，packet=报文内容，数据包
                if (res == 0) {
                    // 超时未收到数据包，告警
                    //std::cout << "超时未收到数据包，告警" << std::endl;
                    SPDLOG_LOGGER_ERROR(my_logger, "超时未收到数据包，告警");
                    continue;
                }
                if(res == -1) {
                    //printf("读取数据包时出错: %s\n", pcap_geterr(handle));
                    SPDLOG_LOGGER_ERROR(my_logger, "读取数据包时出错:{}",pcap_geterr(handle));
                    return -1;
                }

                // 抓包debug
                if (debug == "debug") {
                    SPDLOG_LOGGER_INFO(my_logger, "得到数据包{},长度:{}, caplen/数据包物理长度:{}, 时间:{}.{}", pkgCount, header->len, header->caplen, header->ts.tv_sec, header->ts.tv_usec);
                }
                switch (exchange_id) {
                    case 1: // 广期
                        // 基于时间窗口的统计 = 每3秒一个窗口，记录一次
                    {
                        pkgCount++;
                        // 获取纳秒级时间戳

                        //timeContainer.push_back(header->ts.tv_sec*100000000 + header->ts.tv_usec); // 用抓包时间
                        //timeContainer.push_back(std::chrono::high_resolution_clock::now().time_since_epoch().count()); // 用本地时间
                        //auto ns_since_epoch = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch());
                        auto aa = std::chrono::system_clock::now().time_since_epoch().count()/1000;
                        timeContainer.push_back(aa); // 用本地时间
                        //std::cout << "时间=" << timeContainer.back() << " aa=" << aa << " " << typeid(aa).name() << std::endl;

                        //timeContainer.insert(std::chrono::high_resolution_clock::now().time_since_epoch().count()); // 用本地时间
                        //timeContainer.insert(timeContainer.end(),std::chrono::high_resolution_clock::now().time_since_epoch().count()); // 指定位置插入

/*                    timestamps.push_back(header->ts); // 尾插
                    long diff_us = (timestamps[timestamps.size()-1].tv_sec - timestamps[timestamps.size()-2].tv_sec) * 1000000L +
                                   (timestamps[timestamps.size()-1].tv_usec - timestamps[timestamps.size()-2].tv_usec);
                    total_diff_us += diff_us;*/

                        // 3秒后的时间
                        if (pkgCount % 1000 == 0) {
                            //if (std::chrono::system_clock::now() >= statisticTime + std::chrono::seconds(3)) {
                            statistic_num++;
                            MarketData marketData;
                            memset(&marketData, 0x00, sizeof(MarketData));
                            marketData.lineFlag = sectionId;
                            // 包外数据
                            //marketData.len = header->len; //抓到数据包，长度
                            //marketData.caplen = header->caplen; // header->caplen 数据包物理长度
                            //marketData.time1 = header->ts.tv_sec; // 抓包的秒级时间戳
                            //marketData.time2 = header->ts.tv_usec; // 纳秒级别时间戳
                            // 计算平均时间
                            //marketData.avg_local_time = std::chrono::duration_cast<std::chrono::milliseconds>(timeContainer.back() - timeContainer.front()).count() / (timeContainer.size() - 1);
                            //marketData.avg_local_time = std::accumulate(delayList1.begin(), delayList1.end(), 0) / delayList1.size();
                            //marketData.avg_local_time = std::accumulate(timeContainer.begin(), timeContainer.end(), 0) / timeContainer.size();
                            marketData.statistic_num = statistic_num;

                            // 遍历容器
                            uint64_t sum = std::accumulate(timeContainer.begin(), timeContainer.end(), static_cast<uint64_t>(0));
                            uint64_t avg_timestamp = static_cast<uint64_t>(sum) / timeContainer.size();
                            //std::cout << avg_timestamp << "=总和=" << sum << "=size=" << timeContainer.size() << "\n";

/*                        for (auto it = timeContainer.begin(); it != timeContainer.end(); ++it) {
                            //std::cout << *it << "\n";
                        }*/

                            marketData.avg_local_time = avg_timestamp;


                            // 清空容器
                            timeContainer.clear();

                            marketData.pkgCount = pkgCount; // 包计数器，编号从1开始
                            data_queue->enqueue(marketData); // 在 queue 的尾部添加一个元素的副本

                            statisticTime = std::chrono::system_clock::now();
                        }

                    }
                        break;
                    case 2: // 上期
                    {
                        pkgCount++; // 当前接受的总包数，包数不是连续的？？？

                        MarketData marketData;
                        memset(&marketData, 0x00, sizeof(MarketData));
                        marketData.lineFlag = sectionId;
                        marketData.destinationIP = destinationIP;
                        // 包外数据
                        marketData.len = header->len; //抓到数据包，长度
                        marketData.caplen = header->caplen; // header->caplen 数据包物理长度
                        marketData.time1 = header->ts.tv_sec; // 抓包的秒级时间戳
                        marketData.time2 = header->ts.tv_usec; // 纳秒级别时间戳
                        // 包内毫秒级时间戳
                        //marketData.snap_time = header->ts.tv_sec * 1000 + header->ts.tv_usec / 1000;
                        marketData.local_time = std::chrono::high_resolution_clock::now(); // 本地时间戳，纳秒级别

                        marketData.pkgCount = pkgCount; // 包计数器，编号从1开始

                        // 解析数据包中的数据，传递的数据尽量要少
                        //marketData.pkthdr = header; // 原始包头数据
                        //marketData.packet = packet; // 原始payload数据
                        shfe_decode::parse_packet_shfe(header, packet, marketData, outFile);

                        //data_queue->enqueue(marketData); // 在 queue 的尾部添加一个元素的副本
                        //std::cout << sectionId.data() << ": " << marketData.local_time.time_since_epoch().count()
                        //<< " " << marketData.time1
                        //<< " " << data_queue->getSize() << "\n";
                        //SPDLOG_LOGGER_INFO(my_logger,"{},packet_no={},time1={},time2={},snap_time={},snap_millisec={}",sectionId,marketData.packet_no,marketData.time1,marketData.time2,marketData.snap_time,marketData.snap_millisec);
                    }
                        break;
                    case 3: // 大连
                    {
                        pkgCount++; // 当前接受的总包数，包数不是连续的？？？

                        MarketData marketData;
                        memset(&marketData, 0x00, sizeof(MarketData));
                        marketData.lineFlag = sectionId;
                        // 包外数据
                        marketData.len = header->len; //抓到数据包，长度
                        marketData.caplen = header->caplen; // header->caplen 数据包物理长度
                        marketData.time1 = header->ts.tv_sec; // 抓包的秒级时间戳
                        marketData.time2 = header->ts.tv_usec; // 纳秒级别时间戳
                        // 包内毫秒级时间戳
                        //marketData.snap_time = header->ts.tv_sec * 1000 + header->ts.tv_usec / 1000;
                        marketData.local_time = std::chrono::high_resolution_clock::now(); // 本地时间戳，纳秒级别

                        marketData.pkgCount = pkgCount; // 包计数器，编号从1开始

                        // 解析数据包中的数据，传递的数据尽量要少
                        //marketData.pkthdr = header; // 原始包头数据
                        //marketData.packet = packet; // 原始payload数据
                        //parse_packet_dce(header, packet, marketData);
                        dce_decode::parse_packet_dce(header, packet, marketData);

                        data_queue->enqueue(marketData); // 在 queue 的尾部添加一个元素的副本
                        //std::cout << sectionId.data() << ": " << marketData.local_time.time_since_epoch().count()
                        //<< " " << marketData.time1
                        //<< " " << data_queue->getSize() << "\n";
                    }
                        break;
                    case 4: // 郑州
                    {
                        pkgCount++; // 当前接受的总包数，包数不是连续的？？？

                        MarketData marketData;
                        memset(&marketData, 0x00, sizeof(MarketData));
                        marketData.lineFlag = sectionId;
                        // 包外数据
                        marketData.len = header->len; //抓到数据包，长度
                        marketData.caplen = header->caplen; // header->caplen 数据包物理长度
                        marketData.time1 = header->ts.tv_sec; // 抓包的秒级时间戳
                        marketData.time2 = header->ts.tv_usec; // 纳秒级别时间戳
                        // 包内毫秒级时间戳
                        //marketData.snap_time = header->ts.tv_sec * 1000 + header->ts.tv_usec / 1000;
                        marketData.local_time = std::chrono::high_resolution_clock::now(); // 本地时间戳，纳秒级别

                        marketData.pkgCount = pkgCount; // 包计数器，编号从1开始

                        // 解析数据包中的数据，传递的数据尽量要少
                        //marketData.pkthdr = header; // 原始包头数据
                        //marketData.packet = packet; // 原始payload数据
                        zce_decode::parse_packet_zce(header, packet, marketData, outFile);

                        //data_queue->enqueue(marketData); // 在 queue 的尾部添加一个元素的副本
                        //std::cout << sectionId.data() << ": " << marketData.local_time.time_since_epoch().count()
                        //<< " " << marketData.time1
                        //<< " " << data_queue->getSize() << "\n";
                    }
                        break;
                    case 5: // 中金
                    {
                        if (header->caplen > 60) { // 60字节以上才算正常包？
                            pkgCount++;

                            MarketData marketData;
                            memset(&marketData, 0x00, sizeof(MarketData));
                            marketData.lineFlag = sectionId;
                            // 包外数据
                            marketData.len = header->len; //抓到数据包，长度
                            marketData.caplen = header->caplen; // header->caplen 数据包物理长度
                            marketData.time1 = header->ts.tv_sec; // 抓包的秒级时间戳
                            marketData.time2 = header->ts.tv_usec; // 纳秒级别时间戳
                            // 包内毫秒级时间戳
                            //marketData.snap_time = header->ts.tv_sec * 1000 + header->ts.tv_usec / 1000;
                            marketData.local_time = std::chrono::high_resolution_clock::now(); // 本地时间戳，纳秒级别

                            marketData.pkgCount = pkgCount; // 包计数器，编号从1开始

                            //data_queue->enqueue(marketData); // 在 queue 的尾部添加一个元素的副本

                            // 直接写文件
                            outFile << pkgCount<< ","
                            //<< sourceIP << "," << sourcePort << ","
                            << destinationIP << "," << destinationPort << ","
                            << header->caplen << ","
                            << header->ts.tv_sec << ","
                            << header->ts.tv_usec << ","
                            << std::endl;
                        }

                    }

                        break;
                    default:
                        SPDLOG_LOGGER_ERROR(my_logger,"没有匹配的交易所：exchange_id={}",exchange_id);
                        break;
                }

                // 解析数据包并获取有效数据
                //std::cout << "得到数据包，长度: " << header->len << " caplen/数据包物理长度: " << header->caplen << " 时间: " << header->ts.tv_sec << "." << header->ts.tv_usec << std::endl;
                //compareTraffic.writeTraffic1(*header);
                //parse_packet(header,packet);


                // 判断队列是否可用，队列未满 = 底层是动态扩容的，没有"满"的时候，除非资源耗尽
                //if (header->caplen > 60) // 60字节以上才算正常包？



            }
        } catch (const std::invalid_argument& e) {
            //std::cerr << "Caught an invalid argument: " << e.what() << std::endl;
            SPDLOG_LOGGER_ERROR(my_logger, "无效的参数: {}", e.what());
            // 处理异常，例如提供错误信息、重试操作或者返回错误码
            return -1;
        }
        pcap_close(handle);
        return 0;
    }

    // 从网卡获取，解析后直接写入文件
    int PcapUtils::readNetwork(std::string sectionId, std::chrono::system_clock::time_point startTime, IniReader* iniCfg) {

        // 从配置文件中获取配置
        std::string device = iniCfg->ReadString(sectionId.data(), "device","");
        std::string sourceIP = iniCfg->ReadString(sectionId.data(), "sourceIP","");
        std::string destinationIP = iniCfg->ReadString(sectionId.data(), "destinationIP","");
        std::string destinationPort = iniCfg->ReadString(sectionId.data(), "destinationPort","");
        std::string filterStr = iniCfg->ReadString(sectionId.data(), "filterStr",""); // 抓包过滤条件

        std::string target_time_all = iniCfg->ReadString("MODE", "target_time_all","");

        std::string fileName = "markdata_" + sectionId + "_" + device;
        // 获取当前时间戳并转为字符串
        std::time_t now = std::time(nullptr);
        std::tm* now_tm = std::localtime(&now);
        std::ostringstream oss;
        oss << std::put_time(now_tm, "%Y%m%d_%H%M%S");
        fileName = fileName + "_" + oss.str() + ".txt";
        std::ofstream file(fileName);
        // 检查文件是否成功打开
        if (!file.is_open()) {
            SPDLOG_LOGGER_ERROR(my_logger, "文件打开失败: {}",fileName);
            std::cerr << "文件打开失败: " << fileName << std::endl;
            return -1;
        }

        char errbuf[PCAP_ERRBUF_SIZE];
        pcap_t *handle;

        // 网络接口名称
        const char *dev = device.c_str(); //"ens33";

        // 创建 pcap 句柄
        handle = pcap_create(dev, errbuf);
        if (handle == NULL) {
            fprintf(stderr, "无法创建 pcap 句柄: %s\n", errbuf);
            SPDLOG_LOGGER_ERROR(my_logger, "无法创建 pcap 句柄: %s\n", errbuf);
            return 1;
        }

        // 设置纳秒级时间戳精度
        // 无，PCAP_TSTAMP_PRECISION_NANO(不一定都是9位) ，PCAP_TSTAMP_PRECISION_MICRO
        // t1=1739242273 t2=235530，t1=1739242599 t2=998971747，t1=1739242518 t2=683691
        if (pcap_set_tstamp_precision(handle, PCAP_TSTAMP_PRECISION_NANO) != 0) {// PCAP_TSTAMP_PRECISION_MICRO, PCAP_TSTAMP_PRECISION_NANO
            fprintf(stderr, "设置纳秒级时间戳精度失败: %s\n", pcap_geterr(handle));
            SPDLOG_LOGGER_ERROR(my_logger, "设置纳秒级时间戳精度失败: %s\n", pcap_geterr(handle));
            // 也可以选择在这里退出，如果纳秒级别时间戳是必需的
        }

        // 设置捕获参数
        if (pcap_set_snaplen(handle, 65535) != 0) { // 设置最大捕获长度
            std::cerr << "Error setting snaplen: " << pcap_geterr(handle) << std::endl;
            return -1;
        }

        if (pcap_set_promisc(handle, 1) != 0) { // 设置混杂模式
            std::cerr << "Error setting promiscuous mode: " << pcap_geterr(handle) << std::endl;
            // goto cleanup; 跳转到错误处理逻辑
            return -1;
        }

        //if (pcap_set_timeout(handle, 1000) != 0) { // 设置超时时间（毫秒） = 是否有必要，报错？？？
        //    std::cerr << "Error setting timeout: " << pcap_geterr(handle) << std::endl;
        //    //goto cleanup;
        //    return -1;
        //}

        // 设置即使模式，为了使收到的报文尽快给我们的处理程序，需要设置成immediate模式
        if (pcap_set_immediate_mode(handle, 1) != 0){ // 0:禁用立即模式，1:立即模式，一个是批量，一个是立即收？？？
            std::cerr << "Error setting timeout: " << pcap_geterr(handle) << std::endl;
            return -1;
        }

        // 激活 pcap 句柄
        if (pcap_activate(handle) != 0) {
            fprintf(stderr, "激活 pcap 句柄失败: %s\n", pcap_geterr(handle));
            SPDLOG_LOGGER_ERROR(my_logger, "激活 pcap 句柄失败: %s\n", pcap_geterr(handle));
            pcap_close(handle);
            return 1;
        }

        // 设置过滤器
        struct bpf_program fp;
        char filter_exp2[] = "host 192.168.192.1"; // 过滤IP数据包，等价的写法，c_str 后为 const char *
        const char *filter_exp = filterStr.c_str() ;
        if (pcap_compile(handle, &fp, filter_exp, 0, PCAP_NETMASK_UNKNOWN) < 0) {
            fprintf(stderr, "无法解析过滤器 %s: %s\n", filter_exp, pcap_geterr(handle));
            SPDLOG_LOGGER_ERROR(my_logger, "无法解析过滤器 %s: %s\n", filter_exp, pcap_geterr(handle));
            exit(EXIT_FAILURE);
        }
        if (pcap_setfilter(handle, &fp) < 0) {
            fprintf(stderr, "无法应用过滤器 %s: %s\n", filter_exp, pcap_geterr(handle));
            SPDLOG_LOGGER_ERROR(my_logger, "无法应用过滤器 %s: %s\n", filter_exp, pcap_geterr(handle));
            exit(EXIT_FAILURE);
        }

        // 检查实际的时间戳精度
        int tstamp_precision = pcap_get_tstamp_precision(handle);

        struct pcap_pkthdr *header;
        const u_char *packet;
        int res;

        try {
            auto currentTime = std::chrono::system_clock::now();
            // 当前时间小于指定时间，则忙等
            while ( currentTime.time_since_epoch().count() <= parse_date_to_timestamp(target_time_all)*1000000000 ) {
                // 当前时间小于目标时间，等待100毫秒后再次检查
                //std::this_thread::sleep_for(std::chrono::milliseconds(1));
                std::this_thread::sleep_for(std::chrono::nanoseconds(10)); // 10ns
                currentTime = std::chrono::system_clock::now();
                //std::cout << "1 忙等中。。。" << std::endl;
            }

            std::cout << "pcap开始抓取数据包 tm:" << currentTime.time_since_epoch().count() << " > " << parse_date_to_timestamp(target_time_all)*1000000000 << std::endl;

            SPDLOG_LOGGER_INFO(my_logger,"{} 开始抓取数据",sectionId.data());
            int pkgCount = 0;
            // 捕获循环
            while ((res = pcap_next_ex(handle, &header, &packet)) >= 0 ) { // header=报文头，packet=报文内容，数据包
                if (res == 0) {
                    // 超时未收到数据包，告警
                    std::cout << "超时未收到数据包，告警" << std::endl;
                    continue;
                }
                if(res == -1) {
                    printf("读取数据包时出错: %s\n", pcap_geterr(handle));
                    return -1;
                }

/*                // 打印原始数据
                printf("原始数据:\n");
                for (int i = 0; i < 80*//*header->caplen*//*; i++) {
                    printf("%02x ", packet[i]);
                    if ((i + 1) % 16 == 0) {
                        printf("\n");
                    }
                }*/


                // 判断队列是否可用，队列未满 = 底层是动态扩容的，没有"满"的时候，除非资源耗尽
                {
                    pkgCount++; // 当前接受的总包数，包数不是连续的？？？

                    MarketData marketData;
                    memset(&marketData, 0x00, sizeof(MarketData));
                    marketData.lineFlag = sectionId;
                    // 包外数据
                    marketData.len = header->len; //抓到数据包，长度
                    marketData.caplen = header->caplen; // header->caplen 数据包物理长度
                    marketData.time1 = header->ts.tv_sec; // 抓包的秒级时间戳
                    marketData.time2 = header->ts.tv_usec; // 纳秒级别时间戳
                    marketData.local_time = std::chrono::high_resolution_clock::now(); // 本地时间戳，纳秒级别
                    marketData.pkgCount = pkgCount; // 包计数器，编号从1开始

                    // 解析数据包中的数据
                    //marketData.pkthdr = header; // 原始包头数据
                    //marketData.packet = packet; // 原始payload数据
                    //parse_packet_shfe(header, packet, marketData);
                    //parse_packet_dce(header, packet, marketData);
                    //parse_packet_zce(header, packet, marketData);

                    //data_queue->enqueue(marketData); // 在 queue 的尾部添加一个元素的副本
                    // 直接写入文件
                    //file << marketData.lineFlag << "," // 标识
                    //<< marketData.pkgCount << "," // 包计数器，编号从1开始
                    //<< marketData.packet_no << "," // 报文编号
                    //<< marketData.snap_time << "," // 快照时间
                    //<< marketData.time1 << "," // 抓包时间，秒级时间戳
                    //<< marketData.time2 // 抓包时间，纳秒级时间戳
                    //<< std::endl;
                }
            }

        } catch (const std::invalid_argument& e) {
            std::cerr << "Caught an invalid argument: " << e.what() << std::endl;
            // 处理异常，例如提供错误信息、重试操作或者返回错误码
            return -1;
        }

        pcap_close(handle);
        file.close();
        return 0;
    }


    // 读队列-并计算出所需指标
    int PcapUtils::readMsg(std::shared_ptr<spdlog::logger> _my_logger, IniReader* iniCfg,
                           SafeQueue<MarketData>* data_queue1, SafeQueue<MarketData>* data_queue2, std::string debug) {
        SPDLOG_LOGGER_INFO(my_logger, "===> readMsg");

        //std::cout << "队列大小1" << shareDataClzz->data_queue1.size() << std::endl;
        //std::cout << "消费者：data_queue-队列1大小：" << data_queue1->getSize() << std::endl;
        //sleep(3);
        std::string fileName = "delayFile.txt";
        //std::string fileName = iniCfg->ReadString("MODE", "txt_file_save_path","");
        int exchange_id = iniCfg->ReadInt("MODE", "exchange_id",0);


        std::ofstream file(fileName);
        // 检查文件是否成功打开
        if (!file.is_open()) {
            SPDLOG_LOGGER_ERROR(my_logger, "文件打开失败: {}",fileName);
            //std::cerr << "文件打开失败: " << fileName << std::endl;
            return -1;
        }
        // 表头
        //file << "统计次数,包总数,a比b快的百分比,a减b的时间差" << std::endl;
        // 线程池写文件
        //auto file = fopen(fileName.c_str(), "wt+");

        int lineCount1 = 0;
        int lineCount2 = 0;
        int m1_packet_no = 0;
        int m2_packet_no = 0;
        int pkgCount = 0;
        while (1/*!g_exit*/  && Global::g_exit ==0 ) {
            // 队列不空，则消费数据
            auto a = data_queue1->getSize();
            auto b = data_queue2->getSize();

            // 如果两者都有，则消费，如果两者中有一个没有，则本次跳过，
            // 极限情况，一路有，一路为0，如何处理？？？
            // 为0时如何处理 = 队列为空，则跳过，继续循环
            if (/*1*/a > 0 && b > 0) {
                // 上期非阻塞收
                //MarketData md1 = data_queue1->tryQequeue(); // 实现有问题？ = 队列为空，则返回一个空数据，不会阻塞
                //MarketData md2 = data_queue2->tryQequeue();

                // 郑州要阻塞收
                MarketData md1 = data_queue1->dequeue();
                MarketData md2 = data_queue2->dequeue();

                // 解析数据包中的数据
                //parse_packet(data_queue->dequeue().pkthdr, data_queue->dequeue().packet);

                // 相同包序号下，抓包时间的差值
                // seqNo连续且相同(不为0)时就用其判断
                int delay = NULL;
/*                // shfe ↓↓↓↓↓↓
                if (md1.snap_time != 0 || md2.snap_time != 0) { // 解包的交易所时间不为0，则表示是行情数据包
                    //if ( md1.pkgCount == md2.pkgCount ) {
                        //if (md1.packet_no != 0 ) { // 包序号不为0
                            if (md1.time2 >= md2.time2) { // 1比2块
                                delay = md1.time2 - md2.time2;
                                lineCount1++;
                                std::cout << " delay=" << delay << std::endl;
                            } else { // 2比1块
                                delay = md1.time2 - md2.time2;
                                lineCount2++;
                                std::cout << " delay=" << delay << std::endl;
                            }

                            // pkgNo大的，则接收到的数据包多，行情快
                            //
                    if (md1.packet_no != 0) m1_packet_no = md1.packet_no;
                    if (md2.packet_no != 0) m2_packet_no = md2.packet_no;
                            if (m1_packet_no > m2_packet_no) {
                                // 1快
                                lineCount1++;
                                Line1Count.fetch_add(1);
                                delay = (md1.time1*100000000 + md1.time2) - (md2.time1*100000000 + md2.time2); // 快的纳秒数
                            } else {
                                // 2快
                                lineCount2++;
                                Line2Count.fetch_add(1);
                                delay = (md1.time1*100000000 + md1.time2) - (md2.time1*100000000 + md2.time2);
                            }
                        //}
                        // 行情包编号不同，则用协议头的秒级时间
                        if (md1.time1 == md2.time1) { // 包头秒级时间
                            if (md1.time2 >= md2.time2) { // 1比2块
                                delay = md1.time2 - md2.time2;
                                lineCount1++;
                                std::cout << " delay=" << delay << std::endl;
                            } else { // 2比1块
                                delay = md1.time2 - md2.time2;
                                lineCount2++;
                                std::cout << " delay=" << delay << std::endl;
                            }
                        }
                    //}

                    // 写入文件
                    file << a << "|" << b << "," // 队列大小
                    << md1.pkgCount << "|" << md2.pkgCount << "," // 收到的总包数
                    << md1.packet_no << "|" << md2.packet_no << "," // 行情编号
                    << md1.snap_time << "|" << md2.snap_time << "," // 行情时间戳
                    << md1.time1 << "|" << md2.time1 << "," // 抓包时间戳-秒
                    << md1.time2 << "|" << md2.time2 << "," // 抓包时间戳-纳秒级别
                    << (md1.time1 - md2.time1) << ","  // 时间差值-秒
                    << (md1.time2 - md2.time2) << "," // 时间差值-纳秒级别

                    << lineCount1 << "|" << lineCount2 // a先到达的包数,b先到达的包数
                    //<< delay
                    << std::endl;

                } else {
                    //std::cout << "无效的报文" << std::endl;
                    file << a << "|" << b << "," // 队列大小
                         << md1.pkgCount << "|" << md2.pkgCount << "," // 收到的总包数
                         << md1.packet_no << "|" << md2.packet_no << "," // 行情编号
                         << md1.snap_time << "|" << md2.snap_time << "," // 行情时间戳
                         << md1.time1 << "|" << md2.time1 << "," // 抓包时间戳-秒
                         << md1.time2 << "|" << md2.time2 << "," // 抓包时间戳-纳秒级别
                         << (md1.time1 - md2.time1) << ","  // 时间差值-秒
                         << (md1.time2 - md2.time2) << "," // 时间差值-纳秒级别

                         << lineCount1 << "|" << lineCount2 // a先到达的包数,b先到达的包数
                         //<< delay
                         << std::endl;
                }
                // shfe ↑↑↑↑↑↑*/

/*                // zce ↓↓↓↓↓↓
                // = 包编号相同，那个本地时间小，则那个快
                if (md1.pkgCount == md2.pkgCount) {
                    if (md1.local_time.time_since_epoch().count() <= md2.local_time.time_since_epoch().count()) {
                        lineCount1++;
                    } else {
                        lineCount2++;
                    }

                    //std::cout << "队列data" << " "
                    //<< " lineFlag=" << md1.lineFlag
                    //<< " pkgCount=" << md1.pkgCount
                    //<< " local_time1=" << md1.local_time.time_since_epoch().count()
                    //<< " local_time2=" << md2.local_time.time_since_epoch().count()
                    //<< " time1=" << md1.time1
                    //<< " time2=" << md1.time2
                    //<< " time1=" << md2.time1
                    //<< " time2=" << md2.time2
                    //<< " lineCount=" << lineCount1 << "|" << lineCount2
                    //<< std::endl;

                    file << a << "|" << b << "," // 队列大小
                    << md1.pkgCount << "|" << md2.pkgCount << ","
                    << md1.local_time.time_since_epoch().count() << "|" << md2.local_time.time_since_epoch().count() << ","
                    << md1.local_time.time_since_epoch().count() - md2.local_time.time_since_epoch().count() << ","
                    << md1.time1 << "|" << md2.time1 << "," // 行情时间戳
                    << md1.time2 << "|" << md2.time2 << "," // 行情时间戳
                    << lineCount1 << "|" << lineCount2 << ""
                    << std::endl;
                }
                // zce ↑↑↑↑↑↑*/

                // dce/gfex/cfex ↓↓↓↓↓↓
                // 不解包，采集字段
                // 同一个包
                //std::cout << "同一个包=" << md1.pkgCount << " " << md2.pkgCount << std::endl;
                //if (md1.time1 == md2.time1) {
                if (/*1*/ md1.pkgCount == md2.pkgCount) { // 生产者速度速度不一致，采集字段
                    // 时间差 = 防止 uint64_t 出现整数下溢
                    auto aa = static_cast<long long>(md1.avg_local_time) - static_cast<long long>(md2.avg_local_time);
                    //long long adiff = (md1.time1*1000000000 + md1.time2) - (md2.time1*1000000000 + md2.time2);
                    long long adiff = (md1.local_time - md2.local_time).count();
                    std::string fastFlag = "";
                    if (aa >= 0) {
                        lineCount2++;
                        fastFlag = "l2"; // 时间越大越后到
                    } else {
                        lineCount1++;
                        fastFlag = "l1";
                    }

                    // 更新统计指标
                    pkgCount++;
                    SaveDataStruct saveDataStruct;
                    saveDataStruct.staticCount = pkgCount;
                    saveDataStruct.avgDiff = (saveDataStruct.avgDiff + adiff) / saveDataStruct.staticCount;
                    saveDataStruct.pkgCount1 = md1.pkgCount;
                    saveDataStruct.pkgCount2 = md2.pkgCount;
                    saveDataStruct.lineCount1 = lineCount1;
                    saveDataStruct.lineCount2 = lineCount2;
                    //saveDataStruct.local_time1 = std::chrono::system_clock::now(); // 获取当前时间
                    saveDataStruct.local_time1 = md1.local_time; // 获取当前时间
                    saveDataStruct.local_time2 = md2.local_time; // 获取当前时间
                    saveDataStruct.fastFlag = fastFlag;

                    // 保存到文件
                    // 只采集，不计算
                    file << a << "|" << b << "," // 队列大小
                         << md1.pkgCount << "|" << md2.pkgCount << "," // 收到的总包数
                         //<< md1.packet_no << "|" << md2.packet_no << "," // 行情编号
                         //<< md1.snap_time << "|" << md2.snap_time << "," // 行情时间戳
                         //<< md1.local_time.time_since_epoch().count() << "|" << md2.local_time.time_since_epoch().count() << "," // 本地时间
                         //<< md1.time1 << "|" << md2.time1 << "," // 抓包时间戳-秒
                         //<< md1.time2 << "|" << md2.time2 << "," // 抓包时间戳-纳秒级别
                         //<< (md1.time1 - md2.time1) << ","  // 时间差值-秒
                         //<< (md1.time2 - md2.time2) << "," // 时间差值-纳秒级别

                         << md1.avg_local_time << "|" << md2.avg_local_time << "," // 1000个包的平均时间戳
                         << aa << "," // 时间戳差值
                         << lineCount1 << "|" << lineCount2 << "," // a先到达的包数,b先到达的包数
                         << fastFlag
                         //<< "\n";
                         << std::endl;

                    if (debug == "debug") {
                        std::cout << "队列data" << " "
                        << " lineFlag=" << md1.lineFlag << "|" << md2.lineFlag
                        << " pkgCount=" << md1.pkgCount << "|" << md2.pkgCount
                        << " avg_local_time1=" << md1.avg_local_time << "|" << md2.avg_local_time
                        << " packet_no=" << md1.packet_no << "|" << md2.packet_no
                        << " statistic_num=" << md1.statistic_num << "|" << md2.statistic_num
                        << " time1=" << md1.time1 << "|" << md2.time1 << "," // 抓包时间戳-秒
                        << " time2=" << md1.time2 << "|" << md2.time2 << "," // 抓包时间戳-毫秒/纳秒级别
                        << " 1-2=" << (md1.time1 - md2.time1) << ","  // 时间差值-秒
                        << " 1-2=" << (md1.time2 - md2.time2) << "," // 时间差值-纳秒级别
                        << std::endl;
                    }


                    auto lmd = [](FILE* file, SaveDataStruct sdt, int a,int b) {
                        fprintf(file, "%d|", a);
                        fprintf(file, "%d,", b);

                        fprintf(file, "%d|", sdt.pkgCount1);
                        fprintf(file, "%d,", sdt.pkgCount2);

                        fprintf(file, "%d|", sdt.local_time1.time_since_epoch().count());
                        fprintf(file, "%d,", sdt.local_time2.time_since_epoch().count());

                        fprintf(file, "%d|", sdt.lineCount1);
                        fprintf(file, "%d", sdt.lineCount2);
                        fprintf(file, "\n");

                    };
                    // std::ofstream 会在每个线程结束时自动调用close方法，使其他线程产生未定义行为
                    // FILE* 和 std::ofstream 都不是线程安全的，但 FILE* 更容易通过每个线程独立打开和关闭文件的方式来避免数据竞争。对于 std::ofstream，你需要额外的同步机制（如互斥锁）来确保线程安全
                    //p_t->enqueue(lmd, file, saveDataStruct, a, b);


                    //}


                }

                // dce/gfex/cfex ↑↑↑↑↑↑

            } else {
                continue;
                std::cout << "队列为空" << std::endl;
                //SPDLOG_LOGGER_INFO(my_logger, "队列为空");
            }

        }

        file.close();

        return 0;
    }

// 采样统计 = 跨线程通信要用队列
    int PcapUtils::saveFile(std::shared_ptr<spdlog::logger> _my_logger, IniReader* iniCfg) {
        //std::cout << "readMsg" << std::endl;
        my_logger->info("采样统计");
        //compareTraffic.sampledAndSave(my_logger, iniCfg);

        std::string fileName = "save.txt";

        //FILE *saveFile;
        //saveFile = fopen(fileName.c_str(), "wt+");

        std::ofstream file(fileName);
        // 检查文件是否成功打开
        if (!file.is_open()) {
            _my_logger->info("文件打开失败: {}",fileName);
            std::cerr << "文件打开失败: " << fileName << std::endl;
        }

        std::this_thread::sleep_for(std::chrono::seconds(3));

        while(1) {
            SaveDataStruct sdt;

            // 等待3s
            std::this_thread::sleep_for(std::chrono::seconds(3));
        }


        return 0;
    }



// 解析时间字符串并转换为 time_point =
// tm ---> time_t ---> time_point
/*std::chrono::system_clock::time_point PcapUtils::parseTime(const std::string& timeStr) {
    std::tm tm = {};
    std::istringstream ss(timeStr);

    // 使用 std::get_time 解析时间字符串
    ss << std::get_time(&tm, "%Y-%m-%d %H:%M:%S");

    if (ss.fail()) {
        throw std::runtime_error("Failed to parse time string");
    }

    // 将 struct tm 转换为 time_t
    std::time_t time_t_value = mktime(&tm);

    // 将 time_t 转换为 system_clock::time_point
    auto duration = std::chrono::system_clock::from_time_t(time_t_value);

    // 处理纳秒部分
    std::string nanosecondsStr = timeStr.substr(20);
    std::istringstream nsStream(nanosecondsStr);
    long long nanoseconds;
    nsStream >> nanoseconds;

    // 将纳秒部分添加到 duration
    duration += std::chrono::nanoseconds(nanoseconds);

    return duration;
}*/


// 将时间字符串转换为 time_point
    std::chrono::system_clock::time_point PcapUtils::string_to_time_point(const std::string& str) {
        // 解析字符串
        int year, month, day, hour, minute, second;
        std::istringstream ss(str);
        char delimiter;

        ss >> year >> delimiter >> month >> delimiter >> day >> delimiter
           >> hour >> delimiter >> minute >> delimiter >> second;

        // 创建 tm 结构体
        std::tm tm_struct = {};
        tm_struct.tm_year = year - 1900; // 年份从 1900 开始计算
        tm_struct.tm_mon = month - 1;     // 月份从 0 开始计算
        tm_struct.tm_mday = day;
        tm_struct.tm_hour = hour;
        tm_struct.tm_min = minute;
        tm_struct.tm_sec = second;

        // 转换为 time_t
        std::time_t time_t_value = mktime(&tm_struct);

        // 转换为 time_point
        return std::chrono::system_clock::from_time_t(time_t_value);
    }

// 时间日期转时间戳
// 解析日期字符串并转换为时间戳
    time_t PcapUtils::parse_date_to_timestamp(const std::string& date_str) {
        struct tm time_struct = {};
        const char* format = "%Y-%m-%d %H:%M:%S";

        // 解析日期字符串
        if (strptime(date_str.c_str(), format, &time_struct) == nullptr) {
            std::cerr << "Invalid date format:" << date_str.c_str() << ", " << format << std::endl;
            throw std::invalid_argument("日期格式无效");
        }

        // 将 tm 结构体转换为时间戳
        time_t timestamp = mktime(&time_struct);
        if (timestamp == -1) {
            throw std::runtime_error("Failed to convert to timestamp");
        }

        return timestamp;
    }


} // ntp